#-*- coding:Utf-8 -*-
#!/usr/bin/env python
import random

#TODO créer la classe labyrinthe
class Labyrinthe(object):

    def __init__(self, taille, nbEquipe, tailleParcelles, modeJeu):
        self.parcelles = []
        self.taille=taille #impair only (min 7)
        self.tailleParcelles=tailleParcelles #min5
        self.nbEquipe=nbEquipe #>=2 <=4

        #Si deux equipes : duel (se font face)
        if self.nbEquipe==2:
            for i in range(self.taille*self.taille) :
                #si mode randball
                if(modeJeu==1):
                    #Colonne centrale pour spawn/panier/centre
                    if(i==(self.taille-1)/2):
                        self.parcelles.append(Panier(1, "Nord"))
                    #panier de l'equipe sud
                    elif(i==(self.taille-1)/2+(self.taille-1)*self.taille):
                        self.parcelles.append(Panier(2, "Sud"))
                    #centre map (ballon)
                    elif (i==(self.taille-1)/2+(self.taille)*((self.taille-1)/2)):
                        self.parcelles.append(Centre(0))
                    #du laby
                    else :
                        self.parcelles.append(Parcelle(self.tailleParcelles))
                #du laby
                else :
                    self.parcelles.append(Parcelle(self.tailleParcelles))
        #Sinon carré
        else :
            for i in range(self.taille*self.taille) :
                #si mode randball
                if(modeJeu==1):
                    #Colonne centrale pour spawn/panier/centre
                    if(i==(self.taille-1)/2):
                        self.parcelles.append(Panier(1, "Nord"))
                    #panier de l'equipe ouest
                    elif(i==(self.taille)*((self.taille-1)/2) and self.nbEquipe==4):
                        self.parcelles.append(Panier(2, "Ouest"))
                    #panier de l'equipe est
                    elif(i==((self.taille)*((self.taille-1)/2)+(self.taille-1))):
                        self.parcelles.append(Panier(3, "Est"))
                    #panier de l'equipe sud
                    elif(i==(self.taille-1)/2+(self.taille-1)*self.taille):
                        self.parcelles.append(Panier(4, "Sud"))
                    #centre map (ballon)
                    elif (i==(self.taille-1)/2+(self.taille)*((self.taille-1)/2)):
                        self.parcelles.append(Centre(0))
                    #du laby
                    else :
                        self.parcelles.append(Parcelle(self.tailleParcelles))
                #du laby
                else :
                    self.parcelles.append(Parcelle(self.tailleParcelles))
                    
    def creerLaby(self):
        #Pour chaque parcelle on génère les cases
        for i in range(len(self.parcelles)):
            #paniers et centre
            if self.parcelles[i].isParcelle()==True:
                self.parcelles[i].creerLaby()
            
    
class Panier(object):
    def __init__(self, num,nom):
        self.num=num
        self.nom=nom

    def isParcelle(self):
        return False
                
class Centre(object):
    def __init__(self, num):
        self.num=num

    def isParcelle(self):
        return False
    
#Classe définissant les parcelles de murs
class Parcelle(object):

    def __init__(self, taille):
        self.cases = []
        self.taille=taille

        #On crée les cases
        for i in range(self.taille*self.taille) :
            self.cases.append(Case(i))

    #On génére ici un labyrinthe à partir des cases de la parcelle
    #Toutes les cases sont initialement des murs
    def creerLaby(self) :      
     mursOk=[] #Liste des murs traités
     mursVoisins=[] #Liste des murs en contact avec le mur précédemment traité
     chemins=[] #Liste des chemins (non murs)

     #Ne me demandez pas pourquoi je sais plus, mais il doit avoir une différence quelquepart ...
     total=len(self.cases)
     maxi =len(self.cases)
     
     #Premier cas
     #On commencer par la premiere case (0;0), elle devient un chemin
     #On l'ajoute donc aux murs traités (ok) et aux chemins
     first=0
     self.cases[first].settype("chemin")
     chemins.append(self.cases[first])
     mursOk.append(self.cases[first])

     #On test ensuite tout ses voisins, si ce sont des murs, on les ajoutes à la liste des voisins
     if((first+self.taille)<=maxi): #dessus
         if(self.cases[first+self.taille].gettype()=="mur"):
             mursVoisins.append(self.cases[first+self.taille])
     if((first-self.taille)>=0): #dessous
         if(self.cases[first-self.taille].gettype()=="mur"):
             mursVoisins.append(self.cases[first-self.taille])
     if((first+1)<=maxi): #Droite
         if(self.cases[first+1].gettype()=="mur"):
             mursVoisins.append(self.cases[first+1])
     if((first-1)>=0): #Gauche
         if(self.cases[first-1].gettype()=="mur"):
             mursVoisins.append(self.cases[first-1])

     #On soustrait au total(nombre de cases restantes à traiter)
     #La dernière case traitée devient la first (on note la position)
     total=total-1
     numeroLast = first
     cheminsFoireux=[] #Contient la liste de tous les murs non traités qui ne pourront l'être (faute de quoi le laby ne sera pas parfait)
     k=0 #agent
     
     #Tant qu'il reste des cases qui n'ont pas été traités, on continu !
     while(total!=0):

         #S'il a des voisins
         #On selectionne un mur voisin au piff
         if(len(mursVoisins)!=0):
             case = random.randint(0, len(mursVoisins)-1)
             case = mursVoisins[case]
         #Sinon on selectionne parmi les chemins existants, celle qui prolongera le parcours
         #Il faut donc trouver un chemin, disposant d'au moins un voisin exploitable
         else :
             nouveau = False
             while (nouveau != True):
                 nvoisin=False
                 #Tant qu'on a pas de voisin valide
                 while(nvoisin==False):
                     ##On selectionne un chemin au hasard
                     chemin = random.randint(0, len(chemins)-1)
                     chemin = chemins[chemin]
                     k=0
                     #On s'assure que le chemin soit valide (!= foireux) et qu'il existe
                     while((chemin in cheminsFoireux) and k<len(chemins)):
                         chemin = random.randint(0, len(chemins)-1)
                         chemin = chemins[chemin]
                         k=k+1
                     #Si on a fait tout les chemins sans trouver de valide, on sort de la boucle
                     if(k>=len(chemins)):
                         break
                     #Sinon, le chemin est selectionné
                     chemin = chemin.ident
                     
                     ##On effecute la liste de ses voisins qui sont des murs et non des chemins.
                     voisinsTemp =[]
                     if((chemin+self.taille)<maxi) and (self.cases[chemin+self.taille] in mursOk) and (self.cases[chemin+self.taille].gettype()!="chemin"):
                         voisinsTemp.append(self.cases[chemin+self.taille])
                     if((chemin-self.taille)>=0) and (self.cases[chemin-self.taille] in mursOk)and (self.cases[chemin-self.taille].gettype()!="chemin"):
                         voisinsTemp.append(self.cases[chemin-self.taille])
                     if(((chemin+1)%self.taille) !=0) and (self.cases[chemin+1] in mursOk)and (self.cases[chemin+1].gettype()!="chemin"):
                         voisinsTemp.append(self.cases[chemin+1])
                     if(((chemin)%self.taille) !=0) and (self.cases[chemin-1] in mursOk)and (self.cases[chemin-1].gettype()!="chemin"):
                         voisinsTemp.append(self.cases[chemin-1])

                     ##On séléctionne un voisin au piff
                     if(len(voisinsTemp)>1):
                         voisin1=random.randint(0, len(voisinsTemp)-1)
                         voisin1=voisinsTemp[voisin1]
                         casev1=voisin1.ident
                         nvoisin=True # On a notre voisin ok, on sort de la boucle de recherhce
                     else :
                         if(len(voisinsTemp)!=0):
                             voisin1=voisinsTemp[0]
                             casev1=voisin1.ident
                             nvoisin=True
                         else : #Sinon, le chemin est officiellement inexploitable
                             cheminsFoireux.append(self.cases[chemin])
                             cheminsFoireux=list(set(cheminsFoireux))
                     voisinsTemp[:]=[] #vide

                 if(k>=len(chemins)):
                     break
                
                 ##On test maintenant l'emplacement de la nouvelle case (la voisine):
                 ##Si elle (casev1) est en dessous du chemin
                 if(casev1-self.taille)==chemin:
                     ##On test si l’inverse de celui est bien vide ou inexistant
                     if(casev1+self.taille)>=maxi or self.cases[casev1+self.taille].gettype()=="mur":
                         ##On test s’il a un chemin voisin en commun
                         commun=False
                         if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille].gettype()=="chemin"):
                             commun=True
                         if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1].gettype()=="chemin"):
                             commun=True
                         if(((casev1)%self.taille) !=0) and (self.cases[casev1-1].gettype()=="chemin"):
                             commun=True
                         if(commun==False):
                             ##On enregistre ce voisin comme étant un chemin et ses voisins comme les nouveaux voisins
                             mursOk.append(self.cases[casev1])
                             chemins.append(self.cases[casev1])
                             self.cases[casev1].settype("chemin")
                             case=self.cases[casev1]
                             mursVoisins[:]=[]
                             if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille] in mursOk) and (self.cases[casev1+self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+self.taille])
                             if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille] in mursOk)and (self.cases[casev1-self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-self.taille])
                             if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1] in mursOk)and (self.cases[casev1+1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+1])
                             if(((casev1)%self.taille) !=0) and (self.cases[casev1-1] in mursOk)and (self.cases[casev1-1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-1])
                             total=total-1
                             nouveau = True
                         else :
                             cheminsFoireux.append(self.cases[chemin])
                             cheminsFoireux=list(set(cheminsFoireux))
                     else:
                         cheminsFoireux.append(self.cases[chemin])
                         cheminsFoireux=list(set(cheminsFoireux))
                             
                 ##Si elle (casev1) est en dessus du chemin
                 elif(casev1+self.taille)==chemin:
                     ##On test si l’inverse de celui est bien vide ou inexistant
                     if(casev1-self.taille)<0 or self.cases[casev1-self.taille].gettype()=="mur":
                         ##On test s’il a un chemin voisin en commun
                         commun=False
                         if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille].gettype()=="chemin"):
                             commun=True
                         if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1].gettype()=="chemin"):
                             commun=True
                         if(((casev1)%self.taille) !=0) and (self.cases[casev1-1].gettype()=="chemin"):
                             commun=True
                         if(commun==False):
                             ##On enregistre ce voisin comme étant un chemin et ses voisins comme les nouveaux voisins
                             mursOk.append(self.cases[casev1])
                             chemins.append(self.cases[casev1])
                             self.cases[casev1].settype("chemin")
                             case=self.cases[casev1]
                             mursVoisins[:]=[]
                             if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille] in mursOk) and (self.cases[casev1+self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+self.taille])
                             if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille] in mursOk)and (self.cases[casev1-self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-self.taille])
                             if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1] in mursOk)and (self.cases[casev1+1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+1])
                             if(((casev1)%self.taille) !=0) and (self.cases[casev1-1] in mursOk)and (self.cases[casev1-1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-1])
                             total=total-1
                             nouveau = True
                         else :
                             cheminsFoireux.append(self.cases[chemin])
                             cheminsFoireux=list(set(cheminsFoireux))
                     else:
                         cheminsFoireux.append(self.cases[chemin])
                         cheminsFoireux=list(set(cheminsFoireux))
                             
                 ##Si elle (casev1) est à droite du chemin
                 elif(casev1-1)==chemin:
                     ##On test si l’inverse de celui est bien vide ou inexistant
                     #si au bord ou suivant ==mur
                     if(casev1+1)>=maxi or (((casev1+1)%self.taille) !=0) or self.cases[casev1+1].gettype()=="mur":
                         ##On test s’il a un chemin voisin en commun
                         commun=False
                         if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille].gettype()=="chemin"):
                             commun=True
                         if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille].gettype()=="chemin"):
                             commun=True
                         if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1].gettype()=="chemin"):
                             commun=True
                         if(commun==False):
                             ##On enregistre ce voisin comme étant un chemin et ses voisins comme les nouveaux voisins
                             mursOk.append(self.cases[casev1])
                             chemins.append(self.cases[casev1])
                             self.cases[casev1].settype("chemin")
                             case=self.cases[casev1]
                             mursVoisins[:]=[]
                             if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille] in mursOk) and (self.cases[casev1+self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+self.taille])
                             if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille] in mursOk)and (self.cases[casev1-self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-self.taille])
                             if(((casev1)%self.taille) !=0) and (self.cases[casev1-1] in mursOk)and (self.cases[casev1-1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-1])
                             total=total-1
                             nouveau = True
                         else :
                             cheminsFoireux.append(self.cases[chemin])
                             cheminsFoireux=list(set(cheminsFoireux))
                     else:
                         cheminsFoireux.append(self.cases[chemin])
                         cheminsFoireux=list(set(cheminsFoireux))
                         
                 ##Si elle (casev1) est à gauche du chemin
                 elif(casev1+1)==chemin:
                     ##On test si l’inverse de celui est bien vide ou inexistant
                     if(casev1-1)<0 or (((casev1)%self.taille) !=0) or self.cases[casev1-1].gettype()=="mur":
                         ##On test s’il a un chemin voisin en commun
                         commun=False
                         if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille].gettype()=="chemin"):
                             commun=True
                         if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille].gettype()=="chemin"):
                             commun=True
                         if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1].gettype()=="chemin"):
                             commun=True
                         if(((casev1)%self.taille) !=0) and (self.cases[casev1-1].gettype()=="chemin"):
                             commun=True
                         if(commun==False):
                             ##On enregistre ce voisin comme étant un chemin et ses voisins comme les nouveaux voisins
                             mursOk.append(self.cases[casev1])
                             chemins.append(self.cases[casev1])
                             self.cases[casev1].settype("chemin")
                             case=self.cases[casev1]
                             mursVoisins[:]=[]
                             if((casev1+self.taille)<maxi) and (self.cases[casev1+self.taille] in mursOk) and (self.cases[casev1+self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+self.taille])
                             if((casev1-self.taille)>=0) and (self.cases[casev1-self.taille] in mursOk)and (self.cases[casev1-self.taille].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-self.taille])
                             if(((casev1+1)%self.taille) !=0) and (self.cases[casev1+1] in mursOk)and (self.cases[casev1+1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1+1])
                             if(((casev1)%self.taille) !=0) and (self.cases[casev1-1] in mursOk)and (self.cases[casev1-1].gettype()!="chemin"):
                                 mursVoisins.append(self.cases[casev1-1])
                             total=total-1
                             nouveau = True
                         else :
                             cheminsFoireux.append(self.cases[chemin])
                             cheminsFoireux=list(set(cheminsFoireux))
                     else:
                         cheminsFoireux.append(self.cases[chemin])
                         cheminsFoireux=list(set(cheminsFoireux))

         if(k>=len(chemins)):
             break
         # si case inverse != chemin
         if(True):
             #Si ok :
             # on le definit comme étant un chemin
             for i in range(len(self.cases)):
                 if self.cases[i].ident==case.ident:
                     self.cases[i].settype("chemin")
                     chemins.append(case)
                     mursOk.append(case)
                     if(case in mursVoisins):
                         mursVoisins.remove(case) 
                         
             # on definit les anciens voisins comme étant des mursok
             for j in range(len(mursVoisins)):
                 for i in range(len(self.cases)):
                     if self.cases[i].ident==mursVoisins[j].ident:
                         self.cases[i].settype("murX")
                         mursOk.append(self.cases[i])
                         
             # on definit les nouveaux murs voisins
             first=case.ident
             mursVoisins[:]=[]
             if((first+self.taille)<maxi):
                 if(first+self.taille) in range(len(self.cases)) :
                     if(self.cases[first+self.taille].gettype()=="mur" and (self.cases[first+self.taille] not in mursOk)):
                         mursVoisins.append(self.cases[first+self.taille])
             if((first-self.taille)>=0):
                 if(first-self.taille) in range(len(self.cases)) :
                     if(self.cases[first-self.taille].gettype()=="mur" and (self.cases[first-self.taille] not in mursOk)):
                         mursVoisins.append(self.cases[first-self.taille])
             if((first+1)<=maxi):
                 if(first+1) in range(len(self.cases)) :
                     if((first+1)%self.taille)!=0:
                         if(self.cases[first+1].gettype()=="mur" and (self.cases[first+1] not in mursOk)):
                             mursVoisins.append(self.cases[first+1])
             if((first-1)>=0):
                 if(first-1) in range(len(self.cases)) :
                     if(first%self.taille)!=0:
                         if(self.cases[first-1].gettype()=="mur" and (self.cases[first-1] not in mursOk)):
                            mursVoisins.append(self.cases[first-1])
             total = total-1
             numeroLast=case.ident
             
         else :
             #on le supprime des murs voisins et on déclare comme étant un murok
             mursOk.append(case)
             if(case in  mursVoisins):
                 mursVoisins.remove(case)
         
    #Pour un affichage en joli chiennes de caractères           
    def __str__(self):
        s=""
        l=0
        for i in range(len(self.cases)):
            if(self.cases[i].type=="mur") :
               s=s+"0"
            elif(self.cases[i].type=="murX")  :
                s=s+"X"
            else:
                s=s+"."
            l=l+1
            if(l==self.taille):
                s=s+"\n"
                l=0
            
        return s

    def isParcelle(self):
        return True

#Classe définissant les cases, pour l'instant les seuls types sont : chemins, mur, murX (murX me servait pour l'affichage, faire la différence entre les traités ou non)
#Ensuite s'ajouteront les pièges  
class Case(object):

    def __init__(self, ident):
        self.type="mur"
        self.ident = ident

    def settype(self, valeur):
        self.type=valeur

    def gettype(self):
        return self.type


#n = Labyrinthe(7, 4, 5)
#n.creerLaby()
